#!/usr/bin/env python

# Copyright (c) 2007 Marcelo Lira dos Santos
#
# Author: Marcelo Lira dos Santos <setanta@gmail.com>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 2 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
# USA

import os
import sys
import pygame

import config
from turingmachine import TuringMachine
from graphical_turingmachine import GraphicalTuringMachine
from controls import Controls

import and_gate

pygame.init()
pygame.font.init()

def create_turingmachine():
    tm = TuringMachine()
    # A maquina de turing deste teste.
    states = ['q1', 'q2', 'q3', 'q4', 'q5', 'q6', 'q7', 'q8', 'qa', 'qr']
    tm.set_states(states)
    tm.set_start_state('q1')
    tm.set_accept_state('qa')
    tm.set_reject_state('qr')
    tm.set_input_alphabet(['0', '1', '#'])
    tm.set_tape_alphabet(['x', ' '])

    # Funcao de transicao
    trans_func = {
        'q1': {'0': ('q2', 'x', TuringMachine.RIGHT),
               '1': ('q3', 'x', TuringMachine.RIGHT),
               '#': ('q8', None, TuringMachine.RIGHT)},
        'q2': {'0': ('q2', None, TuringMachine.RIGHT),
               '1': ('q2', None, TuringMachine.RIGHT),
               '#': ('q4', None, TuringMachine.RIGHT)},
        'q3': {'0': ('q3', None, TuringMachine.RIGHT),
               '1': ('q3', None, TuringMachine.RIGHT),
               '#': ('q5', None, TuringMachine.RIGHT)},
        'q4': {'0': ('q6', 'x', TuringMachine.LEFT),
               'x': ('q4', None, TuringMachine.RIGHT)},
        'q5': {'1': ('q6', 'x', TuringMachine.LEFT),
               'x': ('q5', None, TuringMachine.RIGHT)},
        'q6': {'0': ('q6', None, TuringMachine.LEFT),
               '1': ('q6', None, TuringMachine.LEFT),
               'x': ('q6', None, TuringMachine.LEFT),
               '#': ('q7', None, TuringMachine.LEFT)},
        'q7': {'0': ('q7', None, TuringMachine.LEFT),
               '1': ('q7', None, TuringMachine.LEFT),
               'x': ('q1', None, TuringMachine.RIGHT)},
        'q8': {' ': ('qa', None, TuringMachine.RIGHT),
               'x': ('q8', None, TuringMachine.RIGHT)}
    }

    tm.set_transition_function(trans_func)

    return tm

class App:

    def __init__(self):
        size = (800, 480)
        self.screen = pygame.display.set_mode(size)
        self.bg_color = (244, 255, 189)
        self.bg_color = (255, 228, 202)

        pygame.display.set_caption('Turing Machine')
        icon = pygame.image.load(os.path.join(\
                config.data_dir, 'icon.png')).convert_alpha()
        pygame.display.set_icon(icon)
        pygame.mouse.set_visible(1)

        self.is_running = False
        self.holding_right = False

        self.g_turingmachine = GraphicalTuringMachine(self.screen, 'turing_machine.png')
    
        '''
        turingmachine = create_turingmachine()
        #string = '1011#1011'
        string = '101111100011#101111100011'
        #string = '101111100011#000000000000'
        turingmachine.set_string(string)
        '''
    
        self.turingmachine = and_gate.create_and_gate()

        # 1010111 AND 1100100
        string = '11011000111010#'
    
        self.turingmachine.set_string(string)

        self.g_turingmachine.set_turingmachine(self.turingmachine)
        pos = self.g_turingmachine.get_position()

        def do_goto_start():
            self.is_running = False
            self.g_turingmachine.reset()

        def do_goto_end():
            self.turingmachine.compute()

        def do_step_backward():
            self.turingmachine.step_back()

        def do_step_forward():
            self.turingmachine.compute_step()

        def do_play_pause():
            self.is_running = not self.is_running

        self.g_turingmachine.controls.set_callback('goto-start', do_goto_start)
        self.g_turingmachine.controls.set_callback('goto-end', do_goto_end)
        self.g_turingmachine.controls.set_callback('step-backward', do_step_backward)
        self.g_turingmachine.controls.set_callback('step-forward', do_step_forward)
        self.g_turingmachine.controls.set_callback('play-pause', do_play_pause)


    def run(self):
        while True:
            pygame.time.wait(100)
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    sys.exit()

                elif event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_ESCAPE:
                        sys.exit()
                    elif event.key == pygame.K_LEFT:
                       pass
                    elif event.key == pygame.K_RIGHT:
                        holding_right = True
                    elif event.key == pygame.K_UP:
                        pass
                    elif event.key == pygame.K_DOWN:
                        pass
                    elif event.key in (pygame.K_KP_ENTER, pygame.K_RETURN):
                        self.is_running = not self.is_running
                        self.g_turingmachine.play_pause()
                elif event.type == pygame.KEYUP:
                    if event.key == pygame.K_RIGHT:
                        holding_right = False

                elif event.type == pygame.MOUSEBUTTONDOWN:
                    self.g_turingmachine.controls.on_mouse_click(event.pos, event.button)

            if self.holding_right or self.is_running:
                self.turingmachine.compute_step()

            self.screen.fill(self.bg_color)
            self.g_turingmachine.draw()
            pygame.display.flip()


if __name__ == '__main__':
    app = App()
    app.run()

